// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动！任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任！

using Admin.NET.Application.Entity;
using Admin.NET.Application.Service.PlanViews.Dto;
using Admin.NET.Core;
using SqlSugar;

namespace Admin.NET.Application.Service.PlanViews;

/// <summary>
/// 数据筛选服务实现
/// 统一的数据获取入口，所有PlanView模块都通过此服务获取基础数据
/// </summary>
public class DataFilterService : IDataFilterService, ITransient
{
    private readonly ISqlSugarClient _sqlSugarClient;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="sqlSugarClient">数据库客户端</param>
    public DataFilterService(ISqlSugarClient sqlSugarClient)
    {
        _sqlSugarClient = sqlSugarClient;
    }

    /// <summary>
    /// 获取筛选后的计划数据
    /// 复用现有的查询逻辑，确保与原有功能兼容
    /// </summary>
    /// <param name="filter">筛选条件</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>筛选后的计划数据列表</returns>
    public async Task<List<PlanDataCore>> GetFilteredDataAsync(BusinessMonthFilter filter, CancellationToken cancellationToken = default)
    {
        var query = BuildBaseQuery(filter);

        // 使用Select优化，只查询需要的字段
        var result = await query
            .Select(p => new PlanDataCore
            {
                PlanStart = p.PlanStart,
                PlanEnd = p.PlanEnd,
                ActualStart = p.ActualStart,
                ActualEnd = p.ActualEnd,
                ClassName = p.ClassName,
                WorkAreaId = p.WorkAreaId
            })
            .ToListAsync(cancellationToken);

        return result;
    }

    /// <summary>
    /// 获取业务月的日期范围
    /// 直接调用现有的DateTimeUtil.CalculateWorkTimeRange方法
    /// </summary>
    /// <param name="workTime">业务月份，格式如 '2025-07'</param>
    /// <returns>业务月的开始和结束日期</returns>
    public (DateTime startDate, DateTime endDate) GetDateRange(string workTime)
    {
        return DateTimeUtil.CalculateWorkTimeRange(workTime);
    }

    /// <summary>
    /// 获取统一的日期范围（带优先级）
    /// 1) 优先使用显式 RangeStart/RangeEnd；
    /// 2) 否则回退到 WorkTime（yyyy-MM）的业务范围（上月26→本月25）。
    /// </summary>
    /// <param name="filter">筛选条件</param>
    /// <returns>起止时间范围</returns>
    public (DateTime startDate, DateTime endDate) GetDateRange(BusinessMonthFilter filter)
    {
        if (filter.RangeStart.HasValue && filter.RangeEnd.HasValue)
        {
            var start = filter.RangeStart.Value;
            var end = filter.RangeEnd.Value;

            if (end < start)
                throw new ArgumentException("RangeEnd must be greater than or equal to RangeStart");

            return (start, end);
        }

        return GetDateRange(filter.WorkTime);
    }

    /// <summary>
    /// 构建基础查询条件
    /// 复用现有PlanViewService的BuildBaseQuery逻辑
    /// </summary>
    /// <param name="filter">筛选条件</param>
    /// <returns>查询对象</returns>
    private ISugarQueryable<PlanList> BuildBaseQuery(BusinessMonthFilter filter)
    {
        var query = _sqlSugarClient.Queryable<PlanList>();

        // 筛选区域、分类 - 使用索引友好的查询方式
        query = query
            .WhereIF(filter.ClassName != null, u => u.ClassName == filter.ClassName)
            .WhereIF(filter.WorkAreaId != null, u => u.WorkAreaId == filter.WorkAreaId);

        // 关键词搜索优化 - 使用优化的OR条件查询
        if (!string.IsNullOrWhiteSpace(filter.Keyword))
        {
            var keyword = filter.Keyword.Trim();
            
            // 使用优化的OR条件，但添加索引提示
            query = query.Where(u => 
                u.Ch.Contains(keyword) || 
                u.Fd.Contains(keyword) || 
                u.Team.Contains(keyword) || 
                u.Remark.Contains(keyword)
            );
        }

        // 移除时间范围筛选 - 应该获取所有数据，在统计阶段按事件发生日期进行筛选
        // 这样可以确保统计的准确性，避免遗漏跨业务月的计划项目

        // 多租户支持 - 确保数据过滤正确
        return query.ClearFilter<IOrgIdFilter>();
    }
}
